﻿using System;
using System.Linq;

namespace Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL
{
    public class Binding : Microsoft.CSA.FeedSync.FeedSyncLibrarySL.IFeedSyncItem
    {
        #region private variables

        private string m_Title;
        private string m_Description;
        private string m_ID;
        private string m_Name;

        private bool m_DefaultTitleDescription;

        private System.Collections.Generic.List<Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.Field> m_FieldList = new System.Collections.Generic.List<Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.Field>();
        private System.Collections.Generic.Dictionary<string, Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.Field> m_RequiredFieldDictionary = new System.Collections.Generic.Dictionary<string, Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.Field>();
        private System.Collections.Generic.Dictionary<string, Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.Namespace> m_NamespaceDictionary = new System.Collections.Generic.Dictionary<string, Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.Namespace>();
        private System.Collections.Generic.Dictionary<string, Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.PickList> m_PickListDictionary = new System.Collections.Generic.Dictionary<string, Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.PickList>();

        private System.Xml.Linq.XElement m_XElement;

        private Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.BindingCollection m_BindingCollection;

        private Microsoft.CSA.FeedSync.FeedSyncLibrarySL.Sync m_Sync;

        #endregion

        public Binding()
        {
        }

        public Binding(Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.BindingCollection i_BindingCollection, string i_ID, string i_Name, bool i_CreateDefaultTitleDescription)
            : this(i_BindingCollection, i_ID, i_Name, System.String.Empty, System.String.Empty, i_CreateDefaultTitleDescription, System.String.Empty)
        {
        }

        public Binding(Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.BindingCollection i_BindingCollection, string i_ID, string i_Name, bool i_CreateDefaultTitleDescription, string i_By)
            : this(i_BindingCollection, i_ID, i_Name, System.String.Empty, System.String.Empty, i_CreateDefaultTitleDescription, i_By)
        {
        }

        public Binding(Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.BindingCollection i_BindingCollection, string i_ID, string i_Name, string i_Title, string i_Description, bool i_CreateDefaultTitleDescription)
            : this(i_BindingCollection, i_ID, i_Name, System.String.Empty, System.String.Empty, i_CreateDefaultTitleDescription, System.String.Empty)
        {
        }

        public Binding(Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.BindingCollection i_BindingCollection, string i_ID, string i_Name, string i_Title, string i_Description, bool i_CreateDefaultTitleDescription, string i_By)
        {
            m_XElement = this.CreateIdentifierXElement
                (
                i_BindingCollection,
                false
                );

            this.BindingInitialize
                (
                i_ID,
                i_Name,
                i_Title,
                i_Description,
                i_CreateDefaultTitleDescription
                );

            m_XElement = this.CreateIdentifierXElement
                (
                i_BindingCollection,
                false
                );

            m_XElement.SetAttributeValue(Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.Constants.NAME_ATTRIBUTE, m_Name);

            if (!System.String.IsNullOrEmpty(m_Title))
                m_XElement.SetAttributeValue(Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.Constants.TITLE_ATTRIBUTE, m_Title);

            if (!System.String.IsNullOrEmpty(m_Description))
                m_XElement.SetAttributeValue(Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.Constants.DESCRIPTION_ATTRIBUTE, m_Description);

            m_Sync = new Microsoft.CSA.FeedSync.FeedSyncLibrarySL.Sync
                (
                i_BindingCollection.RSSFeed.XDocument,
                i_By,
                System.Guid.NewGuid().ToString()
                );

            if (m_XElement.HasElements)
                m_XElement.FirstNode.AddBeforeSelf(m_Sync.XElement);
            else
                m_XElement.Add(m_Sync.XElement);
        }

        public Binding(System.Xml.Linq.XElement i_BindingXElement, bool i_CreateDefaultTitleDescription)
        {
            if (i_BindingXElement == null)
                throw new System.ArgumentException("i_BindingXElement must be non-null!");

            bool InvalidElement =
                (i_BindingXElement.Name.LocalName != Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.Constants.BINDING_ELEMENT_NAME) ||
                (i_BindingXElement.Name.NamespaceName != Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.Constants.SIMPLE_FEED_BINDINGS_XML_NAMESPACE_URI);

            if (InvalidElement)
                throw new System.ArgumentException("Invalid i_BindingXElement!");

            m_XElement = i_BindingXElement;

            System.Xml.Linq.XElement FeedSyncXElement = i_BindingXElement.Element(Microsoft.CSA.FeedSync.FeedSyncLibrarySL.Constants.FeedSyncXNamespace + Microsoft.CSA.FeedSync.FeedSyncLibrarySL.Constants.SYNC_ELEMENT_NAME);
            if (FeedSyncXElement == null)
                throw new System.ArgumentException("No FeedSync data found for item!");

            m_Sync = new Microsoft.CSA.FeedSync.FeedSyncLibrarySL.Sync
                (
                this,
                FeedSyncXElement
                );

            string ID = m_XElement.Attribute(Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.Constants.ID_ATTRIBUTE).Value;
            string Name = m_XElement.Attribute(Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.Constants.NAME_ATTRIBUTE).Value;

            string Title = System.String.Empty;
            if (m_XElement.Attribute(Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.Constants.TITLE_ATTRIBUTE) != null)
                Title = m_XElement.Attribute(Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.Constants.TITLE_ATTRIBUTE).Value;

            string Description = System.String.Empty;
            if (m_XElement.Attribute(Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.Constants.DESCRIPTION_ATTRIBUTE) != null)
                Description = m_XElement.Attribute(Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.Constants.DESCRIPTION_ATTRIBUTE).Value;

            this.BindingInitialize
                (
                ID,
                Name,
                Title,
                Description,
                i_CreateDefaultTitleDescription
                );

            var NamespaceXElements = i_BindingXElement.Elements(Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.Constants.SimpleFeedBindingsXNamespace + Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.Constants.NAMESPACE_ELEMENT_NAME);

            foreach (System.Xml.Linq.XElement NamespaceXElement in NamespaceXElements)
            {
                Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.Namespace Namespace = new Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.Namespace(NamespaceXElement);

                this.AddNamespace(Namespace, false);
            }

            //  ------------------------------------------------------------------------------
            //  BIG HONKING NOTE: Must process PickLists before Fields for validation purposes

                var PickListXElements = i_BindingXElement.Elements(Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.Constants.SimpleFeedBindingsXNamespace + Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.Constants.PICKLIST_ELEMENT_NAME);

                foreach (System.Xml.Linq.XElement PickListXElement in PickListXElements)
                {
                    Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.PickList PickList = new Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.PickList
                        (
                        this,
                        PickListXElement
                        );

                    this.AddPickList(PickList, false);
                }

            //  ------------------------------------------------------------------------------

            var FieldXElements = i_BindingXElement.Elements(Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.Constants.SimpleFeedBindingsXNamespace + Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.Constants.FIELD_ELEMENT_NAME);

            foreach (System.Xml.Linq.XElement FieldXElement in FieldXElements)
            {
                Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.Field Field = new Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.Field
                    (
                    this,
                    FieldXElement
                    );

                this.AddField(Field, false);
            }
        }

        internal void BindingInitialize(string i_ID, string i_Name, string i_Title, string i_Description, bool i_CreateDefaultTitleDescription)
        {
            m_ID = i_ID;
            m_Name = i_Name;
            m_Title = i_Title;
            m_Description = i_Description;
            m_DefaultTitleDescription = i_CreateDefaultTitleDescription;

            if (i_CreateDefaultTitleDescription)
            {
                if (System.String.IsNullOrEmpty(m_Title))
                {
                    Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.Field Field = new Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.Field
                        (
                        this,
                        Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.Constants.DEFAULT_TITLE_ELEMENT_NAME,
                        Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.Constants.DEFAULT_TITLE_ELEMENT_NAME,
                        true,
                        Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.Field.ContentTypes.text
                        );

                    m_FieldList.Add(Field);
                    m_RequiredFieldDictionary.Add(Field.Element, Field);
                }

                if (System.String.IsNullOrEmpty(m_Description))
                {
                    Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.Field Field = new Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.Field
                        (
                        this,
                        Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.Constants.DEFAULT_DESCRIPTION_ELEMENT_NAME,
                        Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.Constants.DEFAULT_DESCRIPTION_ELEMENT_NAME,
                        false,
                        Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.Field.ContentTypes.html
                        );

                    m_FieldList.Add(Field);
                }
            }
        }

        public Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.BindingCollection BindingCollection
        {
            get
            {
                return m_BindingCollection;
            }

            internal set
            {
                if (value == null)
                    throw new System.ArgumentException("Value must be non-null!");

                m_BindingCollection = value;
            }
        }

        public string ID
        {
            get
            {
                return m_ID;
            }
        }

        public string Name
        {
            get
            {
                return m_Name;
            }
            set
            {
                if (System.String.IsNullOrEmpty(value))
                    throw new System.ArgumentException("value must be non-null!");

                m_Name = value;
                m_XElement.SetAttributeValue(Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.Constants.NAME_ATTRIBUTE, m_Name);
            }
        }

        public string Title
        {
            get
            {
                return m_Title;
            }
            set
            {
                m_Title = value;
                m_XElement.SetAttributeValue(Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.Constants.TITLE_ATTRIBUTE, m_Title);
            }
        }

        public string Description
        {
            get
            {
                return m_Description;
            }
            set
            {
                m_Description = value;
                m_XElement.SetAttributeValue(Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.Constants.DESCRIPTION_ATTRIBUTE, m_Description);
            }
        }

        public bool DefaultTitleDescription
        {
            get
            {
                return m_DefaultTitleDescription;
            }
        }

        public bool HasField(string i_Element)
        {
            Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.Field Field = null;
            return this.FindField(i_Element, out Field);
        }

        public bool FindField(string i_Element, out Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.Field o_Field)
        {
            o_Field = null;

            foreach (Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.Field Field in m_FieldList)
            {
                if (Field.Element == i_Element)
                {
                    o_Field = Field;
                    return true;
                }
            }

            return false;
        }

        public Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.Field GetField(string i_Element)
        {
            Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.Field Field = null;

            if (!this.FindField(i_Element, out Field))
                throw new System.ArgumentException("Invalid id: " + i_Element);

            return Field;
        }

        public System.Collections.Generic.IList<Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.Field> Fields
        {
            get
            {
                return m_FieldList;
            }
        }

        public System.Collections.Generic.IList<Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.Field> RequiredFields
        {
            get
            {
                return new System.Collections.Generic.List<Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.Field>(m_RequiredFieldDictionary.Values);
            }
        }

        public bool HasPickList(string i_ID)
        {
            return m_PickListDictionary.ContainsKey(i_ID);
        }

        public bool FindPickList(string i_ID, out Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.PickList o_PickList)
        {
            o_PickList = null;

            if (!this.HasPickList(i_ID))
                return false;

            o_PickList = m_PickListDictionary[i_ID];

            return true;
        }

        public Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.PickList GetPickList(string i_ID)
        {
            Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.PickList PickList = null;

            if (!this.FindPickList(i_ID, out PickList))
                throw new System.ArgumentException("Invalid id: " + i_ID);

            return PickList;
        }

        public System.Collections.Generic.IList<Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.PickList> PickLists
        {
            get
            {
                return new System.Collections.Generic.List<Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.PickList>(m_PickListDictionary.Values);
            }
        }

        public bool HasNamespace(string i_LocalPrefix)
        {
            return m_NamespaceDictionary.ContainsKey(i_LocalPrefix);
        }

        public bool FindNamespace(string i_LocalPrefix, out Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.Namespace o_Namespace)
        {
            o_Namespace = null;

            if (!this.HasNamespace(i_LocalPrefix))
                return false;

            o_Namespace = m_NamespaceDictionary[i_LocalPrefix];

            return true;
        }

        public Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.Namespace GetNamespace(string i_LocalPrefix)
        {
            Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.Namespace Namespace = null;

            if (!this.FindNamespace(i_LocalPrefix, out Namespace))
                throw new System.ArgumentException("Invalid prefix: " + i_LocalPrefix);

            return Namespace;
        }

        public System.Collections.Generic.IList<Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.Namespace> Namespaces
        {
            get
            {
                return new System.Collections.Generic.List<Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.Namespace>(m_NamespaceDictionary.Values);
            }
        }

        public void AddField(Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.Field i_Field)
        {
            this.AddField
                (
                i_Field,
                true
                );
        }

        internal void AddField(Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.Field i_Field, bool i_AppendXElement)
        {
            if (i_Field == null)
                throw new System.ArgumentException("i_Field must be non-null!");

            if (this.HasField(i_Field.Element))
                throw new System.ArgumentException("Element already exists in Binding!");

            if (!System.String.IsNullOrEmpty(i_Field.PickListID) && (!this.HasPickList(i_Field.PickListID)))
                throw new System.ArgumentException("PickList with id '" + i_Field.PickListID + "' not found!");

            if (!System.String.IsNullOrEmpty(i_Field.PickListID) && (!System.String.IsNullOrEmpty(i_Field.DefaultValue)))
            {
                Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.PickList PickList = this.GetPickList(i_Field.PickListID);

                bool ValidDefaultValue = false;
                foreach (Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.PickListItem PickListItem in PickList.PickListItems)
                {
                    if (PickListItem.Value == i_Field.DefaultValue)
                    {
                        ValidDefaultValue = true;
                        break;
                    }
                }

                if (!ValidDefaultValue)
                    throw new System.ArgumentException("Default value of '" + i_Field.DefaultValue + "' not valid for PickList with id '" + i_Field.PickListID + "'");
            }

            if (i_Field.XElement.Document != m_XElement.Document)
            {
                System.Xml.Linq.XElement ImportedFieldXElement = new System.Xml.Linq.XElement(i_Field.XElement);

                i_Field = new Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.Field
                    (
                    this,
                    ImportedFieldXElement
                    );
            }

            m_FieldList.Add(i_Field);

            if (i_Field.Required)
                m_RequiredFieldDictionary.Add(i_Field.Element, i_Field);

            if (i_AppendXElement)
                m_XElement.Add(i_Field.XElement);

            i_Field.Binding = this;
        }

        public void RemoveField(Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.Field i_Field)
        {
            if (i_Field == null)
                throw new System.ArgumentException("i_Field must be non-null!");

            if (!this.HasField(i_Field.Element))
                throw new System.ArgumentException("i_Field is not associated with Binding!");

            i_Field.XElement.Remove();
            m_FieldList.Remove(i_Field);
            m_RequiredFieldDictionary.Remove(i_Field.Element);
        }

        public void RemoveAllFields()
        {
            for (int Index = m_FieldList.Count - 1; Index >= 0; --Index)
            {
                Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.Field Field = m_FieldList[Index];
                this.RemoveField(Field);
            }
        }

        public void AddPickList(Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.PickList i_PickList)
        {
            this.AddPickList
                (
                i_PickList,
                true
                );
        }

        internal void AddPickList(Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.PickList i_PickList, bool i_AppendXElement)
        {
            if (i_PickList == null)
                throw new System.ArgumentException("i_PickList must be non-null!");

            if (this.HasPickList(i_PickList.ID))
                throw new System.ArgumentException("PickList already exists in Binding!");

            if (i_PickList.XElement.Document != m_XElement.Document)
            {
                System.Xml.Linq.XElement ImportedPickListXElement = new System.Xml.Linq.XElement(i_PickList.XElement);

                i_PickList = new Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.PickList
                    (
                    this,
                    ImportedPickListXElement
                    );
            }

            m_PickListDictionary.Add(i_PickList.ID, i_PickList);

            if (i_AppendXElement)
                m_XElement.Add(i_PickList.XElement);

            i_PickList.Binding = this;
        }

        public void RemovePickList(Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.PickList i_PickList)
        {
            if (i_PickList == null)
                throw new System.ArgumentException("i_PickList must be non-null!");

            if (!m_PickListDictionary.ContainsKey(i_PickList.ID))
                throw new System.ArgumentException("i_PickList is not associated with Binding!");

            i_PickList.XElement.Remove();
            m_PickListDictionary.Remove(i_PickList.ID);
        }

        public void RemoveAllPickLists()
        {
            foreach (Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.PickList PickList in this.PickLists)
                this.RemovePickList(PickList);
        }

        public void AddNamespace(Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.Namespace i_Namespace)
        {
            this.AddNamespace
                (
                i_Namespace,
                true
                );
        }

        internal void AddNamespace(Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.Namespace i_Namespace, bool i_AppendXElement)
        {
            if (i_Namespace == null)
                throw new System.ArgumentException("i_Namespace must be non-null!");

            if (this.HasNamespace(i_Namespace.LocalPrefix))
                throw new System.ArgumentException("Namespace already exists in Binding!");

            if (i_Namespace.XElement.Document != m_XElement.Document)
            {
                System.Xml.Linq.XElement ImportedNamespaceXElement = new System.Xml.Linq.XElement(i_Namespace.XElement);

                i_Namespace = new Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.Namespace(ImportedNamespaceXElement);
            }

            m_NamespaceDictionary.Add(i_Namespace.LocalPrefix, i_Namespace);

            if (i_AppendXElement)
                m_XElement.Add(i_Namespace.XElement);

            i_Namespace.Binding = this;
        }

        public void RemoveNamespace(Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.Namespace i_Namespace)
        {
            if (i_Namespace == null)
                throw new System.ArgumentException("i_Namespace must be non-null!");

            if (!m_NamespaceDictionary.ContainsKey(i_Namespace.LocalPrefix))
                throw new System.ArgumentException("i_Namespace is not associated with Binding!");

            i_Namespace.XElement.Remove();
            m_NamespaceDictionary.Remove(i_Namespace.LocalPrefix);
        }

        public void RemoveAllNamespaces()
        {
            foreach (Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.Namespace Namespace in this.Namespaces)
                this.RemoveNamespace(Namespace);
        }

        public bool CheckXElementForIdentifier(System.Xml.Linq.XElement i_XElement)
        {
            System.Xml.Linq.XElement ExistingReferenceXElement = i_XElement.Element(Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.Constants.SimpleFeedBindingsXNamespace + Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.Constants.REFERENCE_ELEMENT_NAME);
            return (ExistingReferenceXElement != null);
        }

        public System.Xml.Linq.XElement CreateIdentifierXElement(Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.BindingCollection i_BindingCollection)
        {
            return this.CreateIdentifierXElement
                (
                i_BindingCollection,
                true
                );
        }

        public System.Xml.Linq.XElement CreateIdentifierXElement(System.Xml.Linq.XElement i_ParentXElement)
        {
            System.Xml.Linq.XElement BindingReferenceXElement = new System.Xml.Linq.XElement(Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.Constants.SimpleFeedBindingsXNamespace + Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.Constants.REFERENCE_ELEMENT_NAME);

            BindingReferenceXElement.SetAttributeValue
                (
                Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.Constants.ID_ATTRIBUTE,
                m_ID
                );

            return BindingReferenceXElement;
        }

        private System.Xml.Linq.XElement CreateIdentifierXElement(Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.BindingCollection i_BindingCollection, bool i_IsReference)
        {
            string ElementName = "";

            if (i_IsReference)
                ElementName = Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.Constants.REFERENCE_ELEMENT_NAME;
            else
                ElementName = Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.Constants.BINDING_ELEMENT_NAME;

            System.Xml.Linq.XElement BindingReferenceXElement = new System.Xml.Linq.XElement(Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.Constants.SimpleFeedBindingsXNamespace + ElementName);

            BindingReferenceXElement.SetAttributeValue(Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.Constants.ID_ATTRIBUTE, m_ID);

            return BindingReferenceXElement;
        }

        public System.Collections.Generic.Dictionary<string, Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.FieldValue> GetFieldValuesFromXElement(System.Xml.Linq.XElement i_ItemXElement, bool i_IncludeHidden)
        {
            System.Collections.Generic.Dictionary<string, Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.FieldValue> FieldValuesSortedList = new System.Collections.Generic.Dictionary<string, Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.FieldValue>();

            foreach (Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.Field Field in m_FieldList)
            {
                //  Don't return hidden field names/values
                if (Field.Hidden && !i_IncludeHidden)
                    continue;

                string Text = System.String.Empty;

                Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.FieldValue FieldValue = null;

                System.Collections.Generic.IEnumerable<System.Xml.Linq.XElement> FieldXElements;

                System.Xml.Linq.XNamespace XNamespace = null;
                string NamespacePrefix = System.String.Empty;
                int NamespacePrefixIndex = Field.Element.IndexOf(":");
                if (NamespacePrefixIndex != -1)
                {
                    string ElementName = Field.Element.Substring(NamespacePrefixIndex + 1);
                    NamespacePrefix = Field.Element.Substring(0, NamespacePrefixIndex);
                    XNamespace = m_NamespaceDictionary[NamespacePrefix].URI;
                    FieldXElements = i_ItemXElement.Elements(XNamespace + ElementName);
                }
                else
                {
                    FieldXElements = i_ItemXElement.Elements(Field.Element);
                }

                var FieldXElementValues = 
                    from FieldXElement in FieldXElements 
                    select FieldXElement.Value;

                if (Field.Array)
                {
                    FieldValue = new Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.FieldValue(Field.Element, FieldXElementValues.ToArray());
                }
                else
                {
                    if (FieldXElements.Count() > 1)
                        throw new System.Exception("Non-array field with id '" + Field.Element + "' has multiple values!");

                    System.Xml.Linq.XElement FieldXElement = FieldXElements.First();

                    var TextNodes = 
                        from TextNode in FieldXElement.DescendantNodes() 
                        where (TextNode.NodeType == System.Xml.XmlNodeType.Text)
                        select TextNode;

                    bool HasText = (TextNodes.Count() > 0);

                    if (HasText)
                    {
                        System.Xml.Linq.XText XText = (TextNodes.First() as System.Xml.Linq.XText);
                        Text = XText.Value;
                    }

                    FieldValue = new Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.FieldValue(Field.Element, Text);
                }

                FieldValuesSortedList.Add(Field.Element, FieldValue);
            }

            return FieldValuesSortedList;
        }

        public void RemoveFieldValuesForXElement(System.Xml.Linq.XElement i_ItemXElement, System.Collections.Generic.Dictionary<string, Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.FieldValue> i_FieldValueSortedList)
        {
            foreach (Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.FieldValue FieldValue in i_FieldValueSortedList.Values)
            {
                Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.Field Field = this.GetField(FieldValue.ID);

                System.Xml.Linq.XNamespace XNamespace = null;
                string NamespacePrefix = System.String.Empty;
                string ElementName = Field.Element;

                if (ElementName.IndexOf("/") != -1)
                    ElementName = ElementName.Substring(0, ElementName.IndexOf("/"));

                System.Collections.Generic.IEnumerable<System.Xml.Linq.XElement> FieldXElements = null;
                int NamespacePrefixIndex = ElementName.IndexOf(":");
                if (NamespacePrefixIndex != -1)
                {
                    NamespacePrefix = ElementName.Substring(0, NamespacePrefixIndex);
                    XNamespace = m_NamespaceDictionary[NamespacePrefix].URI;
                    ElementName = ElementName.Substring(NamespacePrefixIndex + 1);
                    FieldXElements = i_ItemXElement.Elements(XNamespace + ElementName);
                }
                else
                {
                    FieldXElements = i_ItemXElement.Elements(ElementName);
                }

                foreach (System.Xml.Linq.XElement FieldXElement in FieldXElements)
                    FieldXElement.Remove();
            }
        }

        public void SetFieldValuesForXElement(System.Xml.Linq.XElement i_ItemXElement, System.Collections.Generic.Dictionary<string, Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.FieldValue> i_FieldValueSortedList)
        {
            this.RemoveFieldValuesForXElement
                (
                i_ItemXElement,
                i_FieldValueSortedList
                );

            foreach (Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.FieldValue FieldValue in i_FieldValueSortedList.Values)
            {
                Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.Field Field = this.GetField(FieldValue.ID);

                string[] ElementNames = Field.Element.Split('/');
                string[] NamespacePrefixes = new string[ElementNames.Length];
                string[] NamespaceURIs = new string[ElementNames.Length];

                for (int Index = 0; Index < ElementNames.Length; ++Index)
                {
                    string ElementName = ElementNames[Index];
                    if (ElementName.IndexOf(":") != -1)
                    {
                        string NamespacePrefix = ElementName.Substring(0, ElementName.IndexOf(":"));
                        Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.Namespace Namespace = this.GetNamespace(NamespacePrefix);

                        ElementName = ElementName.Substring(ElementName.IndexOf(":") + 1);
                        NamespacePrefixes[Index] = Namespace.LocalPrefix;
                        NamespaceURIs[Index] = Namespace.URI;
                    }

                    ElementNames[Index] = ElementName;
                }

                if (Field.Array)
                {
                    foreach (string Value in FieldValue.Values)
                    {
                        System.Xml.Linq.XElement FieldValueXElement = Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.MiscHelpers.CreateElementHierarchy
                            (
                            i_ItemXElement,
                            ElementNames,
                            NamespaceURIs,
                            NamespacePrefixes,
                            true
                            );

                        FieldValueXElement.Value = Value;
                    }
                }
                else
                {
                    System.Xml.Linq.XElement FieldValueXElement = Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.MiscHelpers.CreateElementHierarchy
                        (
                        i_ItemXElement,
                        ElementNames,
                        NamespaceURIs,
                        NamespacePrefixes
                        );

                    FieldValueXElement.Value = FieldValue.Value;
                }
            }
        }

        public string[] GetFieldIDsForTitle()
        {
            return Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.MiscHelpers.GetFieldIDsForExpression(m_Title);
        }

        public string[] GetFieldIDsForDescription()
        {
            return Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.MiscHelpers.GetFieldIDsForExpression(m_Description);
        }

        public override string ToString()
        {
            return m_Name;
        }

        #region Microsoft.CSA.FeedSync.FeedSyncLibrarySL.IFeedSyncItem

        public System.Xml.Linq.XElement XElement
        {
            get
            {
                return m_XElement;
            }
        }

        public Microsoft.CSA.FeedSync.FeedSyncLibrarySL.Sync Sync
        {
            get
            {
                return m_Sync;
            }
            set
            {
                m_Sync = value;
            }
        }

        public void Update(System.DateTime? i_WhenDateTime, string i_By)
        {
            m_Sync.Update(i_WhenDateTime, i_By, true);
        }

        public void ResolveConflicts(System.DateTime? i_WhenDateTime, string i_By)
        {
            m_Sync.ResolveConflicts(i_WhenDateTime, i_By, true);
        }

        public void Delete(System.DateTime? i_WhenDateTime, string i_By)
        {
            m_Sync.Delete(i_WhenDateTime, i_By, true);
        }

        public Microsoft.CSA.FeedSync.FeedSyncLibrarySL.IFeedSyncItem Clone()
        {
            System.Xml.Linq.XElement ClonedXElement = new System.Xml.Linq.XElement(m_XElement);
            Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.Binding Binding = new Microsoft.CSA.FeedSync.SimpleFeedBindingsLibrarySL.Binding
                (
                ClonedXElement,
                this.DefaultTitleDescription
                );

            return Binding;
        }

        public Microsoft.CSA.FeedSync.FeedSyncLibrarySL.Sync Initialize(System.Xml.Linq.XElement i_XElement)
        {
            if (i_XElement == null)
                throw new System.ArgumentException("i_XElement must be non-null!");

            bool Initialized =
                (m_XElement != null) ||
                (m_Sync != null);

            if (Initialized)
                throw new System.Exception("Already initialized!");

            m_XElement = i_XElement;

            m_Sync = new Microsoft.CSA.FeedSync.FeedSyncLibrarySL.Sync(this);

            return m_Sync;
        }

        #endregion

    }
}
